package v1

import (
	"errors"
	"net/http"
	"strconv"
	"zhejianglab/gin-apiserver/model"
	"zhejianglab/gin-apiserver/model/request"

	"github.com/astaxie/beego/validation"
	"github.com/gin-gonic/gin"
)

// AddNewVideo create new video
// @Produce  json
// @Tags video
// @Param AddNewVideo body request.VideoInfo true "request.VideoInfo"
// @Success 201 {object} gin.H "{"code":201,"msg":"AddNewVideo successfully"}"
// @Failure 409 {object} gin.H "{"code":500,"msg":"AddNewVideo: Video name is exist"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"AddNewVideo: Video name is invalid"}"
// @Router /api/v1/video/new [post]
func AddNewVideo(c *gin.Context) {
	var err error

	var Video request.VideoInfo
	err = c.ShouldBindJSON(&Video)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error(), "Error Message ": err})
		return
	}
	videoInfo := model.VideoInfo{
		Name:    Video.Name,
		UserID:  Video.UserID,
		FileKey: Video.FileKey,
		Hash:    Video.Hash,
	}

	valid := validation.Validation{}

	// 校验视频名、fileKey的有效性
	valid.Required(Video.Name, "name").Message("视频名称不能为空")
	if valid.HasErrors() {
		err = errors.New("AddNewVideo: Video name is invalid")
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error(), "data": Video.Name})
		return
	}
	valid.Required(Video.FileKey, "fileKey").Message("fileKey")
	if valid.HasErrors() {
		err = errors.New("AddNewVideo: fileKey is invalid")
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error(), "data": Video.Name})
		return
	}

	if model.ExistVideoByName(Video.Name) {
		err = errors.New("AddNewVideo: Video name is exist")
		c.JSON(http.StatusConflict, gin.H{"status": http.StatusConflict, "message": err.Error(), "data": Video.Name})
		return
	}

	data, err := model.AddNewVideo(&videoInfo)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error(), "data": Video.Name})
		return
	}
	video, ok := data.(*model.VideoInfo)
	if !ok {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error(), "data": Video.Name})
		return
	}
	c.JSON(http.StatusCreated, gin.H{"status": http.StatusCreated, "message": "AddNewVideo successfully!", "data": video})
}

// GetVideo get Video info from db
// @Produce  json
// @Tags video
// @Param id path int true "ID"
// @Success 200 {object} gin.H "{"code":200,"msg":"GetVideo successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"GetVideo failed!"}"
// @Router /api/v1/video/{id} [get]
func GetVideo(c *gin.Context) {
	id := c.Param("id")
	data, err := model.GetVideo(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "GetVideo successfully!", "data": data})
}

// GetVideoWithUserID get Video info from db
// @Produce  json
// @Tags video
// @Param id path int true "ID"
// @Success 200 {object} gin.H "{"code":200,"msg":"GetVideo successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"GetVideo failed!"}"
// @Router /api/v1/video/ [get]
func GetVideoWithUserID(c *gin.Context) {

	userID := c.Query("user_id")
	var err error
	if userID == "" {
		data, err := model.GetAllVideos()
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
			return
		}
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "GetVideo successfully!", "data": data})
		return
	}

	data, err := model.GetVideoWithUserID(userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "GetVideo successfully!", "data": data})
}

// UpdateVideo update  Video
// @Produce  json
// @Tags video
// @Param VideoInfo body request.VideoInfo true "request.VideoInfo"
// @Success 201 {object} gin.H "{"code":201,"msg":"UpdateVideo successfully"}"
// @Failure 409 {object} gin.H "{"code":500,"msg":"UpdateVideo: Video name is exist"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"UpdateVideo: Video name is invalid"}"
// @Router /api/v1/video/{id} [put]
func UpdateVideo(c *gin.Context) {
	var err error
	data := make(map[string]interface{})
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	if !model.ExistVideoByID(id) {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "Video id is not exists failed!"})
		return
	}

	var Video request.VideoInfo

	err = c.ShouldBindJSON(&Video)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "UpdateVideo failed!" + err.Error()})
		return
	}

	if Video.Name != "" {
		if model.ExistVideoByName(Video.Name) {
			err = errors.New("UpdateVideo: data is exist")
			c.JSON(http.StatusConflict, gin.H{"status": http.StatusConflict, "message": err.Error(), "data": Video.Name})
			return
		}
		data["name"] = Video.Name
	}

	if Video.FileKey != "" {
		data["fileKey"] = Video.FileKey
	}
	if Video.Hash != "" {
		data["hash"] = Video.Hash
	}
	if Video.UserID != 0 {
		data["user_id"] = Video.UserID
	}

	model.UpdateVideo(id, data)
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "UpdateVideo successfully!", "data": data})
	return

}

// DeleteVideo delete case info from db
// @Produce  json
// @Tags video
// @Param id path int true "ID"
// @Success 200 {object} gin.H "{"code":200,"msg":"DeleteVideo successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"DeleteVideo failed!"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"id is invalid!"}"
// @Router /api/v1/video/{id} [delete]
func DeleteVideo(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}

	valid := validation.Validation{}
	valid.Min(id, 1, "id").Message("ID必须大于0")

	if !valid.HasErrors() {
		if model.ExistVideoByID(id) {
			model.DeleteVideo(id)
			c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "DeleteVideo successfully!", "data": id})
		} else {
			c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "DeleteVideo failed! video is is not exist!"})
			return
		}
	} else {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "id is invalid!"})
		return
	}
}
